﻿using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
using WCS.Infrastructure.Attr;
using WCS.Infrastructure.Dto.Request.Organization;
using WCS.Infrastructure.Dto.Request.Payment;
using WCS.Infrastructure.Dto.Request.User;
using WCS.Infrastructure.Dto.Response.Common;
using WCS.Infrastructure.Dto.Response.User;
using WCS.Infrastructure.EFCore;
using WCS.Infrastructure.IOC;
using WCS.Infrastructure.Tools;
using WCS.Repository.Interface;
using WCS.Service.Instance;
using WCS.Service.Interface;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace WCS.Service.Instance
{
    [Inject]
    public class UserService : BaseService, IUserService
    {
        private readonly UserIOC _userIOC;
        private readonly IConfiguration _configuration;
        private readonly IMemoryCache _memoryCache;
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly ISmsService _smsService;
        private readonly IUnitOfWork _unitOfWork;
        public UserService(IConfiguration configuration, UserIOC userIOC, IMemoryCache memoryCache, IHttpContextAccessor httpContextAccessor
            , ISmsService smsService, IUnitOfWork unitOfWork)
        {
            _userIOC = userIOC;
            _configuration = configuration;
            _memoryCache = memoryCache;
            _httpContextAccessor = httpContextAccessor;
            _smsService = smsService;
            _unitOfWork = unitOfWork;
        }

        /// <summary>
        /// B端登录
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ApiResult> LoginWeChatToBAsync(LoginRequestDto dto)
        {
            if (string.IsNullOrEmpty(dto.Phone) || string.IsNullOrEmpty(dto.Password))
            {
                return GetResult(0, "账号或密码不能为空");
            }

            try
            {
                //var txOptions = new System.Transactions.TransactionOptions
                //{
                //    IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted,
                //    Timeout = TimeSpan.FromMinutes(2)
                //};
                //using var scope = new TransactionScope(TransactionScopeOption.Required, txOptions, TransactionScopeAsyncFlowOption.Enabled);

                var user = await _userIOC._sysUserEFCore.QueryAll(d => d.Phone == dto.Phone).FirstOrDefaultAsync();
                if (user == null)
                {
                    return GetResult(0, "账号未注册，请先注册再尝试登录");
                }

                if (string.IsNullOrEmpty(user.Password))
                {
                    return GetResult(0, "尚未初始化密码，可通过忘记密码后设置新密码登录");
                }

                var verifyPassword = EncryptionUtility.VerifyPassword(dto.Password, user.Password);
                if (!verifyPassword)
                {
                    return GetResult(0, "账号或密码错误");
                }

                if (user.EnableStatus == 0)
                {
                    return GetResult(0, "账号被禁用");
                }

                string code = Config.GUID();
                LoginLog loginlog = new LoginLog()
                {
                    Code = code,
                    Id = Config.GUID(),
                    CreationTime = DateTime.Now,
                    Explain = null,
                    Ip = Config.GetIp(),
                    Result = 0,
                    UserId = user.Id,
                    Account = dto.Phone,
                };

                //user.LastLoginTime = DateTime.Now;
                //await _userIOC._sysUserEFCore.UpdateAsync(user);
                //var userAffected = await _userIOC._sysUserEFCore.SaveChangesAsync();
                //if (userAffected == 0)
                //{
                //    return GetResult(0, "登录失败，请稍后重试！");
                //}

                await _userIOC._loginLogEFCore.AddAsync(loginlog);
                var logAffected = await _userIOC._loginLogEFCore.SaveChangesAsync();
                if (logAffected == 0)
                {
                    return GetResult(0, "登录失败，请稍后重试！");
                }

                //scope.Complete();
                return GetResult(1, data: code);
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// B端用户验证码登录
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ApiResult> LoginVerificationCodeToBAsync(LoginRequestDto dto)
        {
            if (string.IsNullOrEmpty(dto.Phone) || string.IsNullOrEmpty(dto.VerificationCode))
            {
                return GetResult(0, "账号或验证码不能为空");
            }
            try
            {
                var user = await _userIOC._sysUserEFCore.QueryAll(d => d.Phone == dto.Phone).FirstOrDefaultAsync();
                if (user == null)
                {
                    return GetResult(0, "账号未注册，请先注册再尝试登录");
                }

                if (user.EnableStatus == 0)
                {
                    return GetResult(0, "账号被禁用");
                }

                var verifyCodeResult = await _smsService.VerifyCodeAsync(dto.Phone, dto.VerificationCode);

                if (verifyCodeResult == false)
                {
                    return GetResult(0, "验证码错误或已过期，请重新获取验证码");
                }

                string code = Config.GUID();
                LoginLog loginlog = new LoginLog()
                {
                    Code = code,
                    Id = Config.GUID(),
                    CreationTime = DateTime.Now,
                    Explain = null,
                    Ip = Config.GetIp(),
                    Result = 0,
                    UserId = user.Id,
                    Account = dto.Phone,
                };

                await _userIOC._loginLogEFCore.AddAsync(loginlog);
                var logAffected = await _userIOC._loginLogEFCore.SaveChangesAsync();
                if (logAffected == 0)
                {
                    return GetResult(0, "登录失败，请稍后重试！");
                }

                return GetResult(1, data: code);
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// C端微信登录
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ApiResult> LoginWeChatToCAsync(LoginRequestDto dto)
        {

            try
            {
                using var scope = new TransactionScope(TransactionScopeOption.Required, TimeSpan.FromMinutes(2), TransactionScopeAsyncFlowOption.Enabled);

                var userMini = await _userIOC._sysUserMiniProgramEFCore.QueryAll(d => d.OpenId == dto.openid).FirstOrDefaultAsync();
                if (userMini == null)
                {
                    //C端用户 第一次登录，创建账号
                    SysUserMiniProgram userMiniProgram = new SysUserMiniProgram()
                    {
                        Id = Config.GUID(),
                        PlatformType = 1,
                        Name = "微信昵称",
                        OpenId = dto.openid,
                        AppId = dto.appid,
                        UnionId = dto.unionid,
                        CreationTime = DateTime.Now,
                        EnableStatus = 1,
                        IsMain = false
                    };

                    await _userIOC._sysUserMiniProgramEFCore.AddAsync(userMiniProgram);
                    var sysUserMiniProgram = await _userIOC._sysUserMiniProgramEFCore.SaveChangesAsync();
                    if (sysUserMiniProgram == 0)
                        return GetResult(0, "小程序绑定失败，请稍后重试！");
                    userMini = userMiniProgram;
                }
                if (userMini.UnionId == null)
                {
                    userMini.UnionId = dto.unionid;
                }

                if (userMini.EnableStatus == 0)
                    return GetResult(0, "账号被禁用");

                string code = Config.GUID();
                LoginLog loginlog = new LoginLog()
                {
                    Code = code,
                    Id = Config.GUID(),
                    CreationTime = DateTime.Now,
                    Explain = null,
                    Ip = Config.GetIp(),
                    Result = 0,
                    UserId = userMini.Id,
                    Account = userMini.Phone,
                };
                userMini.LastLoginTime = DateTime.Now;

                await _userIOC._loginLogEFCore.AddAsync(loginlog);
                await _userIOC._sysUserMiniProgramEFCore.UpdateAsync(userMini);
                var result = await _userIOC._loginLogEFCore.SaveChangesAsync();


                scope.Complete();
                return GetResult(result, data: code);
            }
            catch (Exception)
            {
                throw;
            }

        }

        /// <summary>
        /// C端支付宝登录
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ApiResult> LoginAlipayPaymentToCAsync(LoginRequestDto dto)
        {
            try
            {
                using var scope = new TransactionScope(TransactionScopeOption.Required, TimeSpan.FromMinutes(2), TransactionScopeAsyncFlowOption.Enabled);
                var userMini = new SysUserMiniProgram();
                if (!string.IsNullOrEmpty(dto.openid))
                    userMini = await _userIOC._sysUserMiniProgramEFCore.QueryAll(d => d.OpenId == dto.openid).FirstOrDefaultAsync();
                if (!string.IsNullOrEmpty(dto.userid))
                    userMini = await _userIOC._sysUserMiniProgramEFCore.QueryAll(d => d.UserId == dto.userid).FirstOrDefaultAsync();
                if (userMini == null)
                {
                    //C端用户 第一次登录，创建账号
                    SysUserMiniProgram userMiniProgram = new SysUserMiniProgram()
                    {
                        Id = Config.GUID(),
                        PlatformType = 2,
                        Name = "支付宝昵称",
                        OpenId = dto.openid,
                        AppId = dto.appid,
                        UnionId = dto.unionid,
                        UserId = dto.userid,
                        CreationTime = DateTime.Now,
                        EnableStatus = 1,
                        IsMain = false
                    };

                    await _userIOC._sysUserMiniProgramEFCore.AddAsync(userMiniProgram);
                    var sysUserMiniProgram = await _userIOC._sysUserMiniProgramEFCore.SaveChangesAsync();
                    if (sysUserMiniProgram == 0)
                        return GetResult(0, "小程序绑定失败，请稍后重试！");
                    userMini = userMiniProgram;
                }

                if (userMini.EnableStatus == 0)
                    return GetResult(0, "账号被禁用");

                string code = Config.GUID();
                LoginLog loginlog = new LoginLog()
                {
                    Code = code,
                    Id = Config.GUID(),
                    CreationTime = DateTime.Now,
                    Explain = null,
                    Ip = Config.GetIp(),
                    Result = 0,
                    UserId = userMini.Id,
                    Account = userMini.Phone,
                };
                userMini.LastLoginTime = DateTime.Now;

                await _userIOC._loginLogEFCore.AddAsync(loginlog);
                await _userIOC._sysUserMiniProgramEFCore.UpdateAsync(userMini);
                var result = await _userIOC._loginLogEFCore.SaveChangesAsync();


                scope.Complete();
                return GetResult(result, data: code);
            }
            catch (Exception)
            {

                throw;
            }
        }

        /// <summary>
        /// 新增用户
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ApiResult> AddUserAsync(UserRequestDto dto)
        {
            try
            {
                using var scope = new TransactionScope(TransactionScopeOption.Required, TimeSpan.FromMinutes(2), TransactionScopeAsyncFlowOption.Enabled);

                string userId = Config.GUID();
                string password = dto.Password ?? string.Empty;//Config.GenerateSecurePassword();
                SysUser user = new SysUser()
                {
                    Id = userId,
                    Phone = dto.Phone,
                    Password = string.IsNullOrEmpty(password) ? password : EncryptionUtility.HashPassword(password),
                    CreationTime = DateTime.Now,
                    EnableStatus = 1,
                    Name = dto.Name,
                };

                await _userIOC._sysUserEFCore.AddAsync(user);
                var result = await _userIOC._sysUserEFCore.SaveChangesAsync();

                if (result == 0)
                    return GetResult(0, "添加用户失败，请稍后重试！");

                scope.Complete();

                return GetResult(result, data: userId);
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 修改账户密码
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ApiResult> UpdateUserPasswordAsync(UserPasswordUpdateRequestDto dto)
        {
            try
            {
                using var scope = new TransactionScope(TransactionScopeOption.Required, TimeSpan.FromMinutes(2), TransactionScopeAsyncFlowOption.Enabled);

                var user = await _userIOC._sysUserEFCore.QueryAll(d => d.Phone == dto.PhoneNumber).FirstOrDefaultAsync();
                if (user == null)
                    return GetResult(message: "当前手机号账户不存在，请重试");
                user.Password = EncryptionUtility.HashPassword(dto.NewPassword);
                await _userIOC._sysUserEFCore.UpdateAsync(user);
                var result = await _userIOC._sysUserEFCore.SaveChangesAsync();
                if (result == 0)
                    return GetResult(0, "修改密码失败，请稍后重试！");
                scope.Complete();

                return GetResult(result);

            }
            catch (Exception)
            {

                throw;
            }
        }

        /// <summary>
        /// 修改用户头像
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ApiResult> UpdateUserAvatarAsync(UserAvatarUpdateRequestDto dto)
        {
            try
            {
                using var scope = new TransactionScope(TransactionScopeOption.Required, TimeSpan.FromMinutes(2), TransactionScopeAsyncFlowOption.Enabled);
                string userId = _httpContextAccessor.HttpContext?.GetCurrentUserId();

                var user = await _userIOC._sysUserEFCore.QueryAll(d => d.Id == userId).FirstOrDefaultAsync();
                if (user == null)
                    return GetResult(message: "当前用户不存在，请稍后重试");
                user.AvatarUrl = dto.AvatarUrl;
                await _userIOC._sysUserEFCore.UpdateAsync(user);
                var result = await _userIOC._sysUserEFCore.SaveChangesAsync();
                if (result == 0)
                    return GetResult(0, "修改头像失败，请稍后重试！");
                scope.Complete();

                return GetResult(result);

            }
            catch (Exception)
            {

                throw;
            }
        }

        /// <summary>
        /// 实名用户信息
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ApiResult> RealNameUserInformationAsync(RealNameUserInformationRequestDto dto)
        {
            try
            {
                var userId = dto.userId ?? _httpContextAccessor.HttpContext?.GetCurrentUserId();
                var user = await _userIOC._sysUserMiniProgramEFCore.QueryAll(d => d.Id == userId).FirstOrDefaultAsync();
                if (user == null)
                    return GetResult(message: "当前用户不存在，请稍后重试");
                if (!string.IsNullOrEmpty(dto.Phone))
                    user.Phone = dto.Phone;
                if (!string.IsNullOrEmpty(dto.RealName))
                    user.RealName = dto.RealName;
                if (!string.IsNullOrEmpty(dto.IdentityCard))
                    user.IdentityCard = dto.IdentityCard;
                await _userIOC._sysUserMiniProgramEFCore.UpdateAsync(user);
                var result = await _userIOC._sysUserMiniProgramEFCore.SaveChangesAsync();
                if (result == 0)
                    return GetResult(message: "实名失败，请稍后重试");

                return GetResult(1);
            }
            catch (Exception)
            {

                throw;
            }
        }

        /// <summary>
        /// 校验实名用户信息
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task<ApiResult> CheckRealNameUserInformationAsync(string? userId)
        {
            try
            {
                userId = userId ?? _httpContextAccessor.HttpContext?.GetCurrentUserId();
                var user = await _userIOC._sysUserMiniProgramEFCore.QueryAll(d => d.Id == userId).FirstOrDefaultAsync();
                if (user == null)
                    return GetResult(message: "当前用户不存在，请稍后重试");

                bool RegisterPhone = false;
                bool RegisterIdentityCard = false;
                if (!string.IsNullOrEmpty(user.Phone))
                    RegisterPhone = true;
                if (!string.IsNullOrEmpty(user.IdentityCard))
                    RegisterIdentityCard = true;

                return GetResult(1, data: new CheckRealNameUserInformationResponseDto()
                {
                    RegisterPhone = RegisterPhone,
                    RegisterIdentityCard = RegisterIdentityCard
                });
            }
            catch (Exception)
            {

                throw;
            }
        }

        /// <summary>
        /// 获取用户列表
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ApiResult> GetUserListAsync(UserRequestDto dto)
        {
            try
            {
                var data = await _userIOC._sysUserEFCore.QueryAll(out int total, dto.Page, dto.Limit,
                    d => (string.IsNullOrEmpty(dto.Key) || d.Name.Contains(dto.Key)),
                    d => d.CreationTime, false).Select(d => new UserRequestDto
                    {
                        Id = d.Id,
                        Name = d.Name,
                        Phone = d.Phone,
                        Email = d.Email,
                        EnableStatus = d.EnableStatus,
                        CreationTime = d.CreationTime,
                        LastLoginTime = d.LastLoginTime,
                    }).ToListAsync();

                return GetResult(1, data: new
                {
                    data,
                    total
                });
            }
            catch (Exception)
            {

                throw;
            }
        }

        /// <summary>
        /// 获取当前用户
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public async Task<ApiResult> GetUserByCodeAsync(string? code)
        {
            // 参数验证
            if (string.IsNullOrEmpty(code))
            {
                return GetResult(0, message: "身份验证未通过: 无效的验证码");
            }
            try
            {
                // 使用注入的_memoryCache替代原来的获取方式
                string cacheKey = $"UserByCode_{code}";
                if (_memoryCache.TryGetValue(cacheKey, out object? cachedResult))
                {
                    return (ApiResult)cachedResult!;
                }

                // 缓存中不存在，执行数据库查询
                // 优化查询：一次性获取登录日志
                var log = await _userIOC._loginLogEFCore.QueryAll(d => d.Code == code).FirstOrDefaultAsync();
                if (log == null)
                {
                    return GetResult(0, message: "身份验证未通过: 登录记录不存在");
                }

                // 获取最后一次登录记录
                var lastLog = await _userIOC._loginLogEFCore.QueryAll(d => d.UserId == log.UserId,
                    d => d.CreationTime, false).FirstOrDefaultAsync();

                if (lastLog == null || lastLog.Code != code)
                {
                    return GetResult(0, message: "身份验证未通过: 登录凭证已失效");
                }

                // 优化查询：根据用户类型只执行一次查询
                object? userData = null;
                int userType = 1; // 1=B端用户,2=C端用户

                // 尝试获取B端用户
                var user = await _userIOC._sysUserEFCore.QueryAll(d => d.Id == lastLog.UserId).AsNoTracking().FirstOrDefaultAsync();
                if (user != null)
                {
                    user.Password = null!; // 清除密码字段值
                    userData = user;
                }
                else
                {
                    // 如果B端用户不存在，尝试获取C端用户
                    userType = 2;
                    var userMini = await _userIOC._sysUserMiniProgramEFCore.QueryAll(d => d.Id == lastLog.UserId).AsNoTracking().FirstOrDefaultAsync();
                    if (userMini != null)
                    {
                        userData = userMini;
                    }
                    else
                    {
                        return GetResult(0, message: "身份验证未通过: 用户不存在");
                    }
                }

                // 构建结果
                var result = GetResult(1, data: userData);

                // 存储到缓存
                var cacheOptions = new MemoryCacheEntryOptions()
                    .SetAbsoluteExpiration(TimeSpan.FromMinutes(30));
                _memoryCache.Set(cacheKey, result, cacheOptions);

                return result;

            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 获取用户虚拟账信息
        /// </summary>
        /// <returns></returns>
        public async Task<ApiResult> GetUserVirtualAccountAsync()
        {
            string userId = _httpContextAccessor.HttpContext?.GetCurrentUserId();
            var virtualAccount = await _userIOC._sysUserEFCore.QueryAll(d => d.Id == userId).Select(d => new UserRequestDto
            {
                Id = d.Id,
                Name = d.Name,
                Phone = d.Phone,
                UnsettledBalance = d.UnsettledBalance,
                WithdrawableBalance = d.WithdrawableBalance,
                DividedBalance = d.DividedBalance,
            }).FirstOrDefaultAsync();

            return GetResult(1, data: virtualAccount);
        }

        /// <summary>
        /// 获取当前用户角色权限
        /// </summary>
        /// <returns></returns>
        public async Task<CurUserRolePermissionResponseDto> GetCurUserRolePermissionAsync()
        {
            try
            {
                var userId = _httpContextAccessor.HttpContext?.GetCurrentUserId();
                var user = await _userIOC._sysUserEFCore.QueryAll(d => d.Id == userId).FirstOrDefaultAsync();
                if (user == null)
                    return null;

                var userRole = await _userIOC._sysUserRoleEFCore.QueryAll(d => d.Id == user.CurrentUserRoleId).FirstOrDefaultAsync();
                if (userRole == null)
                    return null;

                var userRoles = await _userIOC._sysUserRoleEFCore.QueryAll(d => d.UserId == user.Id && d.RoleId == userRole.RoleId).ToListAsync();
                if (userRoles.Count < 1)
                    return null;

                var role = await _userIOC._sysRoleEFCore.QueryAll(d => d.Id == userRole.RoleId).FirstOrDefaultAsync();
                if (role == null)
                    return null;

                CurUserRolePermissionResponseDto curUserRolePermission = new CurUserRolePermissionResponseDto()
                {
                    RoleId = role.Id,
                    RoleName = role.RoleName,
                    RoleType = role.RoleType,
                    OrganizationType = role.OrganizationType,
                    CurrentUserRoleId = user.CurrentUserRoleId,
                    MerchantId = userRole.MerchantId,
                    StoreIds = userRoles.Select(d => d.StoreId)
                    .Where(s => !string.IsNullOrEmpty(s))
                    .Distinct()
                    .ToList(),
                    CodeIds = userRoles.Select(d => d.CodeId)
                   .Where(s => !string.IsNullOrEmpty(s))
                   .Distinct()
                   .ToList(),
                };

                return curUserRolePermission;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 禁用/启用 用户账号（批量）
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>

        public async Task<ApiResult> BanUserAsync(UserRequestDto dto)
        {
            try
            {
                var iq = _userIOC._sysUserEFCore.QueryAll(d => dto.Ids.Contains(d.Id));
                if (!await iq.AnyAsync())
                {
                    return GetResult(message: "参数错误");
                }
                var list = await iq.ToListAsync();
                list.ForEach(d => d.EnableStatus = (int)dto.EnableStatus);
                await _userIOC._sysUserEFCore.UpdateRangeAsync(list);
                var result = await _userIOC._sysUserEFCore.SaveChangesAsync();
                return GetResult(result);
            }
            catch (Exception)
            {

                throw;
            }
        }

        /// <summary>
        /// 删除用户（批量）
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ApiResult> DeleteUserAsync(UserRequestDto dto)
        {
            var iq = _userIOC._sysUserEFCore.QueryAll(d => dto.Ids.Contains(d.Id));
            if (!await iq.AnyAsync())
            {
                return GetResult(message: "参数错误");
            }
            await _userIOC._sysUserEFCore.DeleteRangeAsync(iq);
            var result = await _userIOC._sysUserEFCore.SaveChangesAsync();
            return GetResult(result);
        }


    }
}
